#include <thread>
#include <iostream>
#include <openssl/ssl.h>
#include "httpd.h"
#include "ZlHttpsSocket.h"
#include "ZlHttpSocket.h"
#include "sslh.h"

static int https_sock = -1;
static int http_sock = -1;
int http_port = 8000;
int https_port = 4430;
int proxy_port = 10086;


/*
proxyServer负责判断以及转发
*/
void proxyServer(int sock_fd)
{
    struct sockaddr_in client_name;
    socklen_t client_name_len = sizeof(client_name);
    while (1) {
	ZlHttpSocket zlHttpSocket;
	ZlSocket *sock = &zlHttpSocket;
	if (sock->accept(sock_fd,
			 (struct sockaddr *) &client_name,
			 &client_name_len) != -1) {
	    start_shoveler(sock->getSocket());	//判断以及转发
	    sock->close();
	}
    }
}

void httpServer(int sock_fd)
{

    struct sockaddr_in client_name;
    socklen_t client_name_len = sizeof(client_name);

    while (1) {
	ZlHttpSocket zlHttpSocket;
	ZlSocket *sock = &zlHttpSocket;
	if (sock->accept(sock_fd,
			 (struct sockaddr *) &client_name,
			 &client_name_len) != -1) {
	    accept_request(sock);
	    sock->close();
	}
    }
    close(sock_fd);
}

//TODO:  解密然后转发
void httpsServer(int sock_fd)
{
    struct sockaddr_in client_name;
    socklen_t client_name_len = sizeof(client_name);
    SSL_CTX *ctx = initSSL("ssl/my.cert", "ssl/my.key");
    while (1) {
	ZlHttpsSocket zlHttpsSocket(ctx);
	ZlSocket *sock = &zlHttpsSocket;
	if (sock->accept(sock_fd,
			 (struct sockaddr *) &client_name,
			 &client_name_len) != -1) {
	    accept_request(sock);
	    sock->close();
	}
    }
    close(sock_fd);
    SSL_CTX_free(ctx);
}

int main(void)
{

    https_sock = -1;
    u_short port = https_port;
    https_sock = startup(&port);
    printf("https running on port %d\n", port);


    http_sock = -1;
    port = http_port;
    http_sock = startup(&port);
    printf("http running on port %d\n", port);


    int proxy_sock = -1;
    port = proxy_port;
    proxy_sock = startup(&port);
    printf("http running on port %d\n", port);

    std::thread httpThread(httpServer, http_sock);
    std::thread httpsThread(httpsServer, https_sock);
    std::thread testThread(proxyServer, proxy_sock);
    httpThread.join();
    httpsThread.join();
    testThread.join();
    return (0);
}
